unit ssDblView;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, ExtCtrls, PicFun;

type
  TfrmDblView = class(TFrame)
    pnView: TPanel;
    pnBeforeAdj: TPanel;
    pnAfterAdj: TPanel;
    lbBeforeAdj: TLabel;
    lbAfterAdj: TLabel;
    pbBeforeAdj: TPaintBox;
    pbAfterAdj: TPaintBox;
    procedure pbBeforeAdjPaint(Sender: TObject);
    procedure pbAfterAdjPaint(Sender: TObject);
  private
    { Private declarations }
    FBmpOfBeforeAdj: TBitmap;
    FBmpOfAfterAdj: TBitmap;
    procedure AdjPaintBoxSize(PaintBox: TPaintBox; PicWidth, PicHeight: Integer);
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure InitBitmap(const Bmp: TBitmap);
    procedure InvalidateBmpOfBeforeAdj;
    procedure InvalidateBmpOfAfterAdj;

    property BmpOfBeforeAdj: TBitmap read FBmpOfBeforeAdj;
    property BmpOfAfterAdj: TBitmap read FBmpOfAfterAdj;
  end;

implementation

{$R *.dfm}

{ TfrmDblView }

constructor TfrmDblView.Create(AOwner: TComponent);
begin
  inherited;
  FBmpOfBeforeAdj := TBitmap.Create;
  FBmpOfAfterAdj  := TBitmap.Create;
  FBmpOfBeforeAdj.PixelFormat := pf24bit;
  FBmpOfAfterAdj.PixelFormat  := pf24bit;

  pnBeforeAdj.DoubleBuffered := True;
  pnAfterAdj.DoubleBuffered := True;
end;

destructor TfrmDblView.Destroy;
begin
  FBmpOfBeforeAdj.Free;
  FBmpOfAfterAdj.Free;
  inherited;
end;

procedure TfrmDblView.AdjPaintBoxSize(PaintBox: TPaintBox; PicWidth,
  PicHeight: Integer);
var
  dHScale, dWScale, dScale: Double;
  boxHeight, boxWidth: Integer;
begin
  boxHeight := PaintBox.Parent.ClientHeight -2;
  boxWidth  := PaintBox.Parent.ClientWidth -2;
  if (boxHeight >= PicHeight) and (boxWidth >= PicWidth) then begin
    PaintBox.Width := PicWidth;
    PaintBox.Height := PicHeight;
    PaintBox.Left := (PaintBox.Parent.ClientWidth - PaintBox.Width) div 2;
    PaintBox.Top := (PaintBox.Parent.ClientHeight - PaintBox.Height) div 2;
  end else begin
    dHScale := boxHeight * 1.0 / PicHeight;
    dWScale := boxWidth * 1.0 / PicWidth;
    if dHScale > dWScale then begin
      dScale := dWScale;
    end else begin
      dScale := dHScale;
    end;
    PaintBox.Width := Trunc(PicWidth * dScale);
    PaintBox.Height := Trunc(PicHeight * dScale);
    PaintBox.Left := (PaintBox.Parent.ClientWidth - PaintBox.Width) div 2;
    PaintBox.Top := (PaintBox.Parent.ClientHeight - PaintBox.Height) div 2;
  end;
end;

procedure TfrmDblView.InitBitmap(const Bmp: TBitmap);
var
  dHScale, dWScale, dScale: Double;
begin
  if (pnBeforeAdj.ClientHeight >= Bmp.Height) and (pnBeforeAdj.ClientWidth >= Bmp.Width) then begin
    FBmpOfBeforeAdj.Width := Bmp.Width;
    FBmpOfBeforeAdj.Height := Bmp.Height;
    FBmpOfBeforeAdj.Canvas.Draw(0, 0, Bmp);
  end else begin
    dHScale := pnBeforeAdj.ClientHeight * 1.0 / Bmp.Height;
    dWScale := pnBeforeAdj.ClientWidth * 1.0 / Bmp.Width;
    if dHScale > dWScale then begin
      dScale := dWScale;
    end else begin
      dScale := dHScale;
    end;
    FBmpOfBeforeAdj.Width := Trunc(Bmp.Width * dScale);
    FBmpOfBeforeAdj.Height := Trunc(Bmp.Height * dScale);
    StretchLinear(FBmpOfBeforeAdj, Bmp);
  end;
  FBmpOfAfterAdj.Assign(FBmpOfBeforeAdj);
end;

procedure TfrmDblView.InvalidateBmpOfBeforeAdj;
begin
  AdjPaintBoxSize(pbBeforeAdj, FBmpOfBeforeAdj.Width, FBmpOfBeforeAdj.Height);
  pbBeforeAdj.Invalidate;
end;

procedure TfrmDblView.InvalidateBmpOfAfterAdj;
begin
  AdjPaintBoxSize(pbAfterAdj, FBmpOfAfterAdj.Width, FBmpOfAfterAdj.Height);
  pbAfterAdj.Invalidate;
end;

procedure TfrmDblView.pbBeforeAdjPaint(Sender: TObject);
begin
  pbBeforeAdj.Canvas.Draw(0, 0, FBmpOfBeforeAdj);
end;

procedure TfrmDblView.pbAfterAdjPaint(Sender: TObject);
begin
  pbAfterAdj.Canvas.Draw(0, 0, FBmpOfAfterAdj);
end;

end.
